home *** CD-ROM | disk | FTP | other *** search
- /*
- OCOP.CPP: a diskette copy optimizer
- -------------------------------------
- Garry J. Vass
- Gundhof Str 18
- D6000 Frankfurt 71
- Germany
-
- It is not easy to explain why this utility exists. In 1986,
- I was travelling all over the globe with diskettes. Sometimes
- I arrived at some place only to learn that my diskettes were
- faulty - somewhat embarrassing to say the least. So I wrote
- a small assembler program called OPTCOPY.COM, that copied files
- and read them back 10 times. Reliability went up, but I was
- bothered because I was carrying too many diskettes. I wanted
- reliability and optimization.
-
- In 1988, I wrote SAFECOPY.COM. With this I was satisfied, and
- it worked well for almost 5 years. Some of my Sysop buddies had
- been using OPTCOPY and naturally wanted the upgrade, so I passed
- it around. I even uploaded it to Compuserve and it was still
- there in 1993. Those were the days of DOS 2.1, and being the
- cautious sort, I included a hook that stopped the program from
- running if it encountered anything higher than DOS 3.X (who could
- imagine something beyond DOS 3?).
-
- To my astonishment, DOS survived into DOS 5. To my further
- astonishmment, SAFECOPY had managed to find itself a secure
- niche of users who bitched and wanted a DOS 5 version.
-
- So here is OCOP. It is not great software. It is simply
- a utility that somebody like NORTON or CENTRAL POINT should
- have done in a flashy way. Oh, by the way, it is called
- OCOP (not OCOPY) because of the differences between German
- and American keyboards.
-
- Times change, in these days of virus-infested media, a utility
- of this sort demands source. The source lies below.
-
- If you use this program, keep the source safe because I
- do not plan on issuing upgrades. It works for me.
-
- Rights. I abandon all rights and all responsibility
- associated with this product.
-
- The source compiles under Borland 3.1 with the command
- line bcc -ml ocop.cpp.
-
- */
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- #include <stdio.h> // some basic rtl includes
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <conio.h>
- #include <dir.h>
- #include <dos.h>
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- typedef struct sFI { // your basic heap administration
- struct find_t blk; // structure
- char dirof[ 128 ];
- int status[ 2 ];
- struct sFI *next;
- }sfxxx;
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- struct sFI *Rootdirs = NULL; // some global variables
- struct sFI *Rootfiles = NULL;
- char Cmd[ 200 ];
- char Basecwd[ 128 ];
- char Spec[ 128 ];
- long Total;
- int Flag_subdirs = 0;
- int Flag_usezip = 0;
- char Argv1[ 50 ];
- char Argv2[ 50 ];
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- void drain( void ) // clear the keyboard buffer
- {
- while( kbhit() )
- getch();
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- void hitakey( void ) // take a bold guess what this does...
- {
- printf( "\n\n\n ----->Hit a key..." );
- getch();
- drain();
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int removedoubles( char *s ) // the lazy programmer's method
- { // for getting path names correct
- if( !strlen( s ) ) return( 0 );
- char *p = strstr( s, "\\\\" );
- while( p ) {
- strcpy( p, p + 1 );
- removedoubles( s );
- p = strstr( s, "\\\\" );
- }
- return( 1 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int insertdirlist( char *s, struct find_t *b ) // stuff a directory
- {
- struct sFI *n;
- n = (struct sFI *)malloc( sizeof( struct sFI ) );
- if( n ) {
- memmove( &n -> blk, b, sizeof( struct find_t ) );
- strcpy( n -> dirof, s );
- memset( n -> status, 0, 4 * sizeof( int ) );
- n -> next = NULL;
- if( !Rootdirs ) {
- Rootdirs = n;
- } else {
- n -> next = Rootdirs;
- Rootdirs = n;
- }
- return( 1 );
- }
- return( 0 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int insertfilelist( char *s, struct find_t *b ) // stuff a file
- {
- struct sFI *n;
- n = (struct sFI *)malloc( sizeof( struct sFI ) );
- if( n ) {
- memmove( &n -> blk, b, sizeof( struct find_t ) );
- removedoubles( s );
- strcpy( n -> dirof, s );
- memset( n -> status, 0, 4 * sizeof( int ) );
- n -> next = NULL;
- if( !Rootfiles ) {
- Rootfiles = n;
- } else {
- if( n -> blk.size > Rootfiles -> blk.size ) {
- n -> next = Rootfiles;
- Rootfiles = n;
- } else {
- struct sFI *p = Rootfiles;
- for( struct sFI *i = Rootfiles; i; i = i -> next ) {
- if( n -> blk.size > i -> blk.size ) {
- n -> next = i;
- p -> next = n;
- return( 1 );
- }
- if( !i -> next ) {
- i -> next = n;
- return( 1 );
- }
- p = i;
- }
- }
- }
- return( 1 );
- }
- return( 0 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int walkcopied( void ) // stroll down the list of copied files
- {
- int ret = 0;
- for( struct sFI *i = Rootfiles; i; i = i -> next ) {
- if( i -> status[ 0 ] ) {
- printf( "%s\\%s %ld ...copied....\n", i -> dirof, i -> blk.name, i -> blk.size );
- drain();
- }
- }
- return( ret );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int walknotcopied( void ) // stroll down the list of files yet to come.
- {
- int ret = 0;
- for( struct sFI *i = Rootfiles; i; i = i -> next ) {
- if( !i -> status[ 0 ] ) {
- printf( "%s\\%s %ld ...not copied....\n", i -> dirof, i -> blk.name, i -> blk.size );
- printf( "\ta. next file\n" );
- printf( "\tb. forget about this file - skip it\n" );
- printf( "\tc. exit the walker\n" );
- drain();
- char c = toupper( getch() );
- switch( c ) {
- case 'B':
- i -> status[ 0 ] = 2;
- break;
- case 'C':
- return( ret );
- }
- }
- }
- return( ret );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int walkdriver( void ) // manage the strolling process
- {
- int ret = 0;
- walktop:
- clrscr();
- printf( "a. Walk files that have been copied\n" );
- printf( "b. Walk files not yet copied\n" );
- printf( "q. Leave the walker\n" );
- drain();
- ret = toupper( getch() );
- switch( ret ) {
- case 'A':
- walkcopied();
- goto walktop;
- case 'B':
- walknotcopied();
- goto walktop;
- case 'Q':
- return( 1 );
- default:
- goto walktop;
- }
- return( ret );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int more( long *total ) // anything else to do?
- {
- int ret = 0;
- *total = 0L;
- for( struct sFI *i = Rootfiles; i; i = i -> next ) {
- if( !i -> status[ 0 ] ) {
- ++ret;
- *total += i -> blk.size;
- }
- }
- return( ret );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- struct sFI *select( long m ) // find a file of length less than "m"
- {
- for( struct sFI *i = Rootfiles; i; i = i -> next ) {
- if( i -> blk.size < m && i -> status[ 0 ] == 0 ) {
- return( i );
- }
- }
- return( NULL );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int builddirlist( char *p, char *s ) // build a heap of directories
- {
- char temp[ 128 ];
- struct find_t blk;
- int done;
- strcpy( temp, p );
- sprintf( Spec, "%s\\%s", temp, s );
- removedoubles( Spec );
- done = _dos_findfirst( Spec , 0xFF, &blk );
- while( !done ) {
- if( blk.attrib == FA_DIREC) {
- if( blk.name[ 0 ] != '.' ) {
- insertdirlist( p, &blk );
- sprintf( temp, "%s\\%s", p, blk.name );
- builddirlist( temp, s );
- }
- }
- done = _dos_findnext( &blk );
- }
- return( 0 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int scandir( char *pname, char *dname, char *args ) // look in the directory
- {
- char temp[ 128 ];
- struct find_t blk;
- sprintf( temp, "%s\\%s\\%s", pname, dname, args );
- removedoubles( temp );
- int done = _dos_findfirst( temp, 0xFF, &blk );
- while( !done ) {
- switch( blk.attrib ) {
- case FA_RDONLY:
- case FA_HIDDEN:
- case FA_LABEL:
- case FA_SYSTEM:
- case 0x28:
- case FA_DIREC:
- break;
- case FA_ARCH:
- default:
- sprintf( temp, "%s\\%s", pname, dname );
- insertfilelist( temp, &blk );
- break;
- }
- done = _dos_findnext( &blk );
- }
- return( 1 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int buildfilelist( char *s ) // build a list of files
- {
- for( struct sFI *d = Rootdirs; d; d = d -> next ) {
- scandir( d -> dirof, d -> blk.name, s );
- }
- return( 0 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int driveexists( char *s ) // lazy programmer's way to see if a drive exists
- {
- unsigned current;
- unsigned md;
- unsigned t;
- unsigned target = *s - 'A' + 1;
- _dos_getdrive( ¤t );
- _dos_setdrive( target, &md );
- _dos_getdrive( &t );
- _dos_setdrive( current, &md );
- if( t == target ) {
- return( 1 );
- }
- return( 0 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- long dfs( char *s ) // just what it says <g>. disk free space.
- {
- struct diskfree_t free;
- long avail;
- clrscr();
- gotoxy( 1, 1 ); printf( "Checking free space on %s", s );
- int dnumber = *s - 'A' + 1;
- if( _dos_getdiskfree( dnumber, &free ) != 0 ) {
- return( 0 );
- }
- avail = (long)free.avail_clusters * (long)free.bytes_per_sector* (long) free.sectors_per_cluster;
- gotoxy( 1, 1 ); printf( "%-4s reports %12ld bytes available", s, avail );
- return( avail );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int parseargs( int argc, char *argv[] ) // the VERY lazy programmer's
- { // way to parse the command tail.
- char allargs[ 128 ];
- char *p;
- /*
- ARGV CONTENTS
- --------------------
- 1 source specification (*.*, etc)
- 2 destination drive (a:, etc)
- 3 optional /s (re xcopy)
- 4 optional /z (use pkzip where possible)
- */
- strcpy( allargs, "" );
- for( int i = 1; i < argc; i++ ) {
- strupr( argv[ i ] );
- strcat( allargs, argv[ i ] );
- }
- if( strstr( allargs, "/S" ) )
- Flag_subdirs = 1;
- if( strstr( allargs, "/Z" ) ) {
- if( searchpath( "PKZIP.COM" ) || searchpath( "PKZIP.EXE" ) ) {
- Flag_usezip = 1;
- } else {
- printf( "Cannot find PKZIP.COM or PKZIP.EXE\n" );
- return( 0 );
- }
- }
- strcpy( Argv1, argv[ 1 ] );
- strcpy( Argv2, argv[ 2 ] );
- if( !driveexists( Argv2 ) ) {
- printf( "Unable to locate destination drive %s\n", Argv2 );
- return( 0 );
- }
- return( 1 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int quit( void ) // hmmmm... I can't remember what this does...
- {
- chdir( Basecwd );
- printf( "You are now in %s\n", Basecwd );
- exit( 0 );
- return( 1 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- char drive[ 25 ];
- char dir[ 128 ];
- char name[ 25 ];
- char ext[ 25 ];
- char Dest[ 128 ];
- int dothework( char *ddrive, struct sFI *s ) // here is where the work
- { // gets done...
- if( Flag_usezip && !( strstr( s -> blk.name, ".ZIP" ) ) ) {
- fnsplit( s -> blk.name, drive, dir, name, ext );
- sprintf( Cmd, "pkzip -a %s%s.zip %s\\%s ", ddrive, name, s -> dirof, s -> blk.name, ddrive );
- sprintf( Dest, "%s%s.ZIP", ddrive, name );
- } else {
- sprintf( Cmd, "xcopy %s\\%s %s", s -> dirof, s -> blk.name, ddrive );
- sprintf( Dest, "%s%s", ddrive, s -> blk.name );
- }
- removedoubles( Cmd );
- gotoxy( 1, 3 );printf( "%-79s\n", Cmd );
- system( Cmd );
- if( kbhit() ) {
- return( 0 );
- }
- sprintf( Cmd, "copy %s NUL", Dest );
- removedoubles( Cmd );
- gotoxy( 1, 8 );printf( "%-79s\n", Cmd );
- system( Cmd );
- return( 1 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int pl( void ) // select a file and copy it
- {
- while( more( &Total ) ) {
- long df = dfs( Argv2 );
- if( kbhit() ) {
- break;
- }
- if( df == 0 ) {
- break;
- }
- struct sFI *s = select( df );
- if( s ) {
- gotoxy( 1, 2 ); printf( "%-14s (%10ld) selected ", s -> blk.name, s -> blk.size );
- s -> status[ 0 ] += dothework( Argv2, s );
- }
- }
- return( 1 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
- int main( int argc, char *argv[] )
- {
- int m;
- int ch;
- clrscr();
- getcwd( Basecwd, 128 );
- if( argc < 3 ) {
- printf( "OCOPY: a diskette optimizer\n" );
- printf( "----------------------------\n" );
- printf( "usage: ocop [spec] [dest] {options}\n\n" );
- printf( " spec = source file specification\n" );
- printf( " dest = destination drive\n" );
- printf( " options\n" );
- printf( " /S = include subdirectories\n" );
- printf( " /Z = use PKZIP where appropriate\n\n\n" );
- printf( "example: ocop *.* a: /S /Z\n" );
- quit();
- }
- if( parseargs( argc, argv ) ) {
- if( Flag_subdirs ) {
- builddirlist( Basecwd, "*.*" );
- buildfilelist( Argv1 );
- }
- scandir( Basecwd, "", Argv1 );
- } else {
- quit();
- }
- restart:
- m = more( &Total );
- long df = dfs( Argv2 );
- if( m ) {
- mtop:
- clrscr();
- drain();
- printf( "There are yet %d files (%ld bytes) left to copy\n", m, Total );
- printf( "There are %ld bytes left on %s\n", df, Argv2 );
- printf( "Menu: \n" );
- printf( "a. continue coping (i.e., %s is ready)\n", Argv2 );
- printf( "d. perform a DIR on %s \n", Argv2 );
- printf( "c. perform a chkdsk on %s\n", Argv2 );
- printf( "e. erase the files on %s\n", Argv2 );
- printf( "f. dothework the diskette in %s\n", Argv2 );
- printf( "s. shell exit to dos\n", Argv2 );
- printf( "w. walk the list of files\n" );
- printf( "q. quit this program\n" );
- drain();
- ch = toupper( getch() );
- clrscr();
- switch( ch ) {
- case 'A':
- pl();
- goto restart;
- case 'C':
- sprintf( Cmd, "chkdsk %s /f", Argv2 );
- system( Cmd );
- drain();
- hitakey();
- goto restart;
- case 'D':
- sprintf( Cmd, "DIR %s /p", Argv2 );
- system( Cmd );
- drain();
- hitakey();
- goto restart;
- case 'E':
- sprintf( Cmd, "erase %s*.*", Argv2 );
- printf( "%s\n", Cmd );
- system( Cmd );
- drain();
- hitakey();
- goto restart;
- case 'F':
- sprintf( Cmd, "dothework %s /u", Argv2 );
- system( Cmd );
- drain();
- hitakey();
- goto restart;
- case 'Q':
- quit();
- case 'S':
- printf( "DOS doorway, type EXIT to return\n" );
- system( "COMMAND" );
- goto restart;
- case 'W':
- walkdriver();
- goto restart;
- default:
- goto restart;
- }
- }
- return( 0 );
- }
- /***************************************************************/
- /* */
- /* */
- /* */
- /* */
- /***************************************************************/
-
-